﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Pipes.Queries
{
  /// <summary>
  /// Elements are added to the top of the list instead of the end.
  /// </summary>
  /// <typeparam name="T"></typeparam>
  public class ReverseList<T> : IList<T>
  {
    private List<T> _list;

    private int Invert(int index)
    {
      return _list.Count - index - 1;
    }

    public ReverseList()
    {
      _list = new List<T>();
    }
    public ReverseList(int capacity)
    {
      _list = new List<T>(capacity);
    }
    public ReverseList(IEnumerable<T> values)
    {
      _list = new List<T>(values);
    }

    public int IndexOf(T item)
    {
      return Invert(_list.IndexOf(item));
    }

    public void Insert(int index, T item)
    {
      _list.Insert(_list.Count - index, item);
    }

    public void RemoveAt(int index)
    {
      _list.RemoveAt(Invert(index));
    }

    public T this[int index]
    {
      get
      {
        return _list[Invert(index)];
      }
      set
      {
        _list[Invert(index)] = value;
      }
    }

    public void Add(T item)
    {
      _list.Add(item);
    }
    public void Push(T item)
    {
      _list.Add(item);
    }
    public T Peek()
    {
      return _list[_list.Count - 1];
    }
    public T Pop()
    {
      T obj  = _list[_list.Count - 1];
      _list.RemoveAt(_list.Count - 1);
      return obj;
    }

    public void Clear()
    {
      _list.Clear();
    }

    public bool Contains(T item)
    {
      return _list.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
      var i = arrayIndex;
      for (var j = _list.Count - 1; j >= 0; j--)
      {
        array[i] = _list[j];
        i++;
      }
    }

    public int Count
    {
      get { return _list.Count; }
    }

    public bool IsReadOnly
    {
      get { return false; }
    }

    public bool Remove(T item)
    {
      return _list.Remove(item);
    }

    public IEnumerator<T> GetEnumerator()
    {
      return _list.Reverse<T>().GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
      return _list.Reverse<T>().GetEnumerator();
    }

  }
}
